<?php
// no direct access
defined('_JEXEC') or die('Restricted access');

jimport('joomla.application.component.controllerform');
jimport('joomla.plugin.plugin');
jimport('joomla.filesystem.file');

/**
 * Example System Plugin
 *
 * @package	    Develope J3 
 * @subpackage	Manage Uploading Files
 * @class       plgmanageFiles
 * @since       1.6.0
 */
class plgmanageFiles extends JPlugin
{

    var $message = "";

    /**
     * Constructor
     *
     * For php4 compatability we must not use the __constructor as a constructor for plugins
     * because func_get_args ( void ) returns a copy of all passed arguments NOT references.
     * This causes problems with cross-referencing necessary for the observer design pattern.
     *
     * @access	      protected
     * @param	object	$subject The object to observe
     */
    function plgmanageFiles(&$subject, $config)
    {
        parent::__construct($subject, $config);

        // Do some extra initialisation in this constructor if required
    }

    protected function arrange_files()
    {
        $getFiles = JRequest::get('files');
        $getFiles = $getFiles['jform'];
        $files = array();
        $ii = 0;
        foreach ($getFiles as $k => $file) {
            foreach ($file as $i => $f) {
                foreach ($f as $l => $t) {
                    $files[$i][$l][$k] = $t;
                }
            }
        }
        return $files;
    }

    /**
     * @final 04/16/2012
     * @param type $images
     * @return boolean 
     */
    function bind_files(&$arr_file, &$data)
    {
        // Check if process image is needed
        $needProcess = false;

        // Assign images
        $arrFiles = $this->arrange_files();
        $file = new stdClass();
        foreach ($arrFiles as $k => $files) {
            foreach ($files as $key => &$value) {
                $delName = JRequest::getVar("{$key}_del");
                if (isset($data[$k][$key . "_field_value"])) {
                    $data[$k][$key] = $data[$k][$key . "_field_value"];
                    unset($data[$k][$key . "_field_value"]);
                }
                $file->name = $key;
                $file->details = $value;
                if (isset($data[$k][$key . "_directory"])) {
                    $file->directory = $data[$k][$key . "_directory"];
                    unset($data[$k][$key . "_directory"]);
                }
                if (isset($data[$k][$key . "_resize_directory"])) {
                    $file->resize_directory = $data[$k][$key . "_resize_directory"];
                    unset($data[$k][$key . "_resize_directory"]);
                }
                if (isset($data[$k][$key . "_resize"])) {
                    $file->resize = $data[$k][$key . "_resize"];
                    unset($data[$k][$key . "_resize"]);
                }
                if (isset($data[$k][$key . "_ext"])) {
                    $file->ext = $data[$k][$key . "_ext"];
                    unset($data[$k][$key . "_ext"]);
                }
                if (isset($data[$k][$key . "_width"])) {
                    $file->width = $data[$k][$key . "_width"];
                    unset($data[$k][$key . "_width"]);
                }
                if (isset($data[$k][$key . "_height"])) {
                    $file->height = $data[$k][$key . "_height"];
                    unset($data[$k][$key . "_height"]);
                }
                if (isset($data[$k][$key . "_encode_name"])) {
                    $file->encode_name = $data[$k][$key . "_encode_name"];
                    unset($data[$k][$key . "_encode_name"]);
                }
                $file->type = $k;
                if ((isset($file->details['name']) && $file->details['name'] && !$needProcess) || $delName) {
                    $needProcess = true;
                }
                $path = JPATH_ROOT . '/' . $file->directory;
                $file->current_image = isset($data[$k][$key]) && $data[$k][$key] ? $data[$k][$key] : "";
                $file->process = ($delName) ?
                ((isset($file->details['name']) && $file->details['name']) ? array("-", "+") : array("-")) :
                ((isset($file->details['name']) && $file->details['name']) ? array("+") : NULL);
//                $file->process = array("+");
                if (!$value['name'] && !$delName) {
                    continue;
                }
                $arr_file[] = $file;
                unset($file);
            }
        }
        return $needProcess;
    }

    function encode($fileName, $key)
    {
        $fileExt = JFile::getExt($fileName);
        $secret_string = md5(date("Y/m/d/H/i/s/$key"));
        $fileName = $secret_string . '.' . $fileExt;
        return $fileName;
    }

    function normalChangeName($name, $path)
    {
        while (file_exists($path . "/" . strtolower($name)) || file_exists($path . "/" . $name)) {
            $pathArr = pathinfo($name);
            $ext = $pathArr['extension'];
            $pathArr['filename'] = JApplication::stringURLSafe(strtolower(strtolower($pathArr['filename'])));
            $fileName = $pathArr['dirname'] != "." ? $pathArr['dirname'] . "/" . $pathArr['filename'] : $pathArr['filename'];
            $name = $fileName . "_" . $_SERVER['REQUEST_TIME'] . rand(0, 9) . "." . $ext;
        }
        return $name;
    }

    /**
     * @author Pham Quang
     * @param type $data
     * @return boolean 
     */
    function uploads($data)
    {
        $path = "";
        $files = NULL;

        // Check if there is some input file or image
        $needProcess = $this->bind_files($files, $data);
        if ($needProcess) {
            /*************************\
            |* Description :         *|
            |* - This code Process   *|
            |*    upload images      *|
            \*************************/
            foreach ($files as $key => $img) {
                $path = "";
                $pathResize = "";
                $resize = FALSE;
                $resized_name = "";
                if ($img->directory) {
                    $path = JPATH_ROOT . '/' . $img->directory;
                }
                if (isset($img->resize_directory) && $img->resize_directory) {
                    $pathResize = JPATH_ROOT . '/' . $img->resize_directory;
                }
                if (is_array($img->process)) {
                    $tmp_name = NULL;
                    // Check and excute image
                    foreach ($img->process as $p) {
                        // Delete image and clear data value
                        if ($p == "-") {
                            if ($this->delete(array($img->current_image), $path)) {
                                // Clear data value
                                $data[$img->type][$img->name] = '';
                            }
                            if ($pathResize || $img->resize) {
                                $this->delete(array($img->resize), $pathResize);
                            }
                        }
                        // Upload image and fill data value
                        if ($p == "+") {
                            // Make the filename safe
                            $img->details['name'] = str_replace(" ", "_", $img->details['name']);
                            if ($img->encode_name) {
                                $img->details['name'] = $this->encode($img->details['name'], $key);
                            } else {
                                $img->details['name'] = $this->normalChangeName($img->details['name'], $path);
                            }
                            $img->details['name'] = strtolower($img->details['name']);
                            if ($path) {
                                if ($this->upload($img->details, $path) || 1) {
                                    $tmp_name = $img->details['tmp_name'];
                                    if (!is_null($tmp_name) && $tmp_name && ($img->width || $img->height)) {
                                        // Try resize if needed after upload
                                        $dimension = array($img->width, $img->height);
                                        $resized_name = $this->resize_image($img->details['name'], $path, $dimension, $pathResize);
                                    }
                                    // Fill data value
                                    $data[$img->type][$img->name] = $img->details['name'];
                                    if ($resized_name) {
                                        $data[$img->type][$img->name . "_resize"] = $resized_name;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            /*********\
            |*  End  *|
            \*********/
        }
        return $data;
    }

    function resize_image($image = "", $path = JPATH_ROOT, $dimension = array(0, 0), $resizeTo = JPATH_ROOT, $resizeName = "")
    {
        require_once (__DIR__) . '/image.php';
        // Make a copy of file to other directory
        if ($resizeTo) {
            $resizeName = $resizeName ? $resizeName : $this->normalChangeName($image, $path);
            if (JFile::copy($path . "/" . $image, $resizeTo . "/" . $resizeName)) {
                $path = $resizeTo;
                $image = $resizeName;
            } else {
                JLog::add(JText::_("Cannot copy file to {$resizeTo}, File name: $resizeName"), JLog::WARNING);
                return FALSE;
            }
        }
        if (is_array($dimension) && count($dimension)) {
            $img = new image();
            $filepath = JPath::clean($path . "/" . $image);
            $img->load($filepath);
            if ($dimension[0] && !$dimension[1]) {
                $img->resizeToWidth($dimension[0]);
            } else if (!$dimension[0] && $dimension[1]) {
                $img->resizeToHeight($dimension[1]);
            } else {
                $img->resize($dimension[0], $dimension[1]);
            }
            $img->save($filepath);
        }
        return ($resizeTo ? $resizeName : $image);
    }

    /**
     * Upload a file
     *
     * @since 1.5
     */
    function upload($file = NULL, $path = "/", $pathCopy = "")
    {
        require_once (__DIR__) . '/defines.php';
        // Check for request forgeries
        require_once JPATH_COMPONENT . '/../com_media/helpers/media.php';
        JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));

        // Get the user
        $user = JFactory::getUser();

        // Set FTP credentials, if given
        JClientHelper::setCredentialsFromRequest('ftp');

        if (isset($file['name'])) {
            // The request is valid
            $err = null;
            if (!MediaHelper::canUpload($file, $err)) {
                // The file can't be upload
                JLog::add(JText::_($err), JLog::WARNING);
                return false;
            }

            $filepath = JPath::clean($path . '/' . strtolower($file['name']));

            // Trigger the onContentBeforeSave event.
            JPluginHelper::importPlugin('content');
            $dispatcher = JDispatcher::getInstance();
            $object_file = new JObject($file);
            $object_file->filepath = $filepath;
            $result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file));
            if (in_array(false, $result, true)) {
                // There are some errors in the plugins
                JLog::add(JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('<br />', $errors)), JLog::WARNING);
                return false;
            }
            $file = (array) $object_file;

            if (JFile::exists($file['filepath'])) {
                // File exists
                JLog::add(JText::_('COM_MEDIA_ERROR_FILE_EXISTS'), JLog::WARNING);
                return false;
            } elseif (!$user->authorise('core.create', 'com_media')) {
                // File does not exist and user is not authorised to create
                JLog::add(JText::_('COM_MEDIA_ERROR_CREATE_NOT_PERMITTED'), JLog::ERROR);
                return false;
            }

            // Make a copy of file to other directory
            if ($pathCopy) {
                $pathCopy = JPath::clean($pathCopy . '/' . strtolower($file['name']));
                JFile::copy($file['tmp_name'], $pathCopy);
            }
            if (!JFile::upload($file['tmp_name'], $file['filepath'])) {
                // Error in upload
                JLog::add(JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'));
                return false;
            } else {
                // Trigger the onContentAfterSave event.
                $dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true));
                JControllerForm::setMessage(JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', substr($file['filepath'], strlen($path))));
                return true;
            }
        } else {
            return false;
        }
    }

    /**
     * Deletes paths from the current path
     *
     * @param string $listFolder The image directory to delete a file from
     * @since 1.5
     */
    function delete($delete, $path)
    {
        JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));
        $app = &JFactory::getApplication();

        // Get some data from the request
        $files = $delete;
        $folder = $path;

        // Set FTP credentials, if given
        JClientHelper::setCredentialsFromRequest('ftp');

        // Initialise variables.
        $ret = true;

        if (count($files)) {
            JPluginHelper::importPlugin('content');
            $dispatcher = JDispatcher::getInstance();
            foreach ($files as $file) {
                if ($file) {
                    if ($file !== JFile::makeSafe($file)) {
                        // filename is not safe
                        $filename = htmlspecialchars($file, ENT_COMPAT, 'UTF-8');
                        JLog::add(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FILE_WARNFILENAME', substr($filename, strlen(COM_MEDIA_BASE))), JLog::WARNING);
                        continue;
                    }

                    $fullPath = JPath::clean($folder . '/' . $file);
                    $object_file = new JObject(array('filepath' => $fullPath));
                    if (is_file($fullPath)) {
                        // Trigger the onContentBeforeDelete event.
                        $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.file', &$object_file));
                        if (in_array(false, $result, true)) {
                            // There are some errors in the plugins
                            JLog::add(JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors = $object_file->getErrors()), implode('<br />', $errors)), JLog::WARNING);
                            continue;
                        }

                        $ret &= JFile::delete($fullPath);

                        // Trigger the onContentAfterDelete event.
                        $dispatcher->trigger('onContentAfterDelete', array('com_media.file', &$object_file));
                        JControllerForm::setMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($fullPath, strlen(COM_MEDIA_BASE))));
                    } elseif (is_dir($fullPath)) {
                        if (count(JFolder::files($fullPath, '.', true, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX'), array('index.html', '^\..*', '.*~'))) == 0) {
                            // Trigger the onContentBeforeDelete event.
                            $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.folder', &$object_file));
                            if (in_array(false, $result, true)) {
                                // There are some errors in the plugins
                                JLog::add(JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors = $object_file->getErrors()), implode('<br />', $errors)), JLog::WARNING);
                                continue;
                            }

                            $ret &= JFolder::delete($fullPath);

                            // Trigger the onContentAfterDelete event.
                            $dispatcher->trigger('onContentAfterDelete', array('com_media.folder', &$object_file));
                            JControllerForm::setMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($fullPath, strlen(COM_MEDIA_BASE))));
                        } else {
                            //This makes no sense...
                            JLog::add(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_NOT_EMPTY', substr($fullPath, strlen(COM_MEDIA_BASE))), JLog::WARNING);
                        }
                    }
                }
            }
            return $ret;
        }
    }

}

// END PLUGIN  Files
?>
